grammar LocCmd;

tokens {
INPUT='-i';
FOCI='-f';
STAT='-s';
INLINE_START='{';
INLINE_STOP='}';
DEBUG='--debug';
VERBOSE='--verbose';
PRINT='--print';
SILENT='--silent';
FILTER='--filter';
TABLE='--table';
REPLACE_STAT='-r';
HELP='--help';
}


@header {
	package ui.grammar;
	
	import java.io.File;
	import java.io.InputStream;
	import ui.UserInterface;
}

@members {
	private UserInterface ui;
	
	public LocCmdParser(TokenStream in, UserInterface ui) {
		this(in);
		this.ui = ui;
	}
	
	@Override
	public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException {
		throw e;
	}
	
	@Override
	protected Object recoverFromMismatchedToken (IntStream input, int ttype, BitSet follow) throws RecognitionException {
		throw new MismatchedTokenException(ttype, input);
	}
}

DELIM
	:   '\r\n'
    ;
    
STRING
	:	~('\t'|'\r'|'\n')+
	;

args
scope{boolean inOpts;}
@init{$args::inOpts = false;}
	:	HELP DELIM EOF {ui.help();}
	|	HELP DELIM STRING DELIM EOF {ui.help($STRING.text);}
	|	(DEBUG DELIM {ui.setDebugMode(true);})?
		input
		DELIM FOCI DELIM a=script {$args::inOpts=true;}
		(b=DELIM STAT DELIM (r=REPLACE_STAT DELIM)? c=script)?
		(DELIM optAtom)*
		DELIM EOF
		{
		ui.parseInput();
		ui.setFociScript($a.in);
		if ($b != null) {
			ui.setStatScript($c.in, $r != null);
		}
		}
	;
	catch [RecognitionException e] {
		if ($args::inOpts) {
			ui.getErrorLogger().logErrorMsg("Error: Invalid option(s). Type 'java -jar <jarfile> --help' for usage information.");
		} else {
			ui.getErrorLogger().logErrorMsg("Error: invalid arguments. Type 'java -jar <jarfile> --help' for usage information.");
		}
		throw new RuntimeException();
	}
	
input
	:	INPUT DELIM a=file {ui.loadInputFile($a.f);} (DELIM b=file {ui.loadInputFile($b.f);})*
	;
	
file returns [File f]
	:	STRING {$f = ui.retrieveFile($STRING.getText());}
	;
	catch [RecognitionException e] {
		ui.getErrorLogger().logErrorMsg("Error: Invalid filepath.");
		throw new RuntimeException();
	}
	
script returns [InputStream in]
	:	INLINE_START DELIM STRING DELIM INLINE_STOP {$in = ui.buildInputStream($STRING.getText());}
	|	file {$in = ui.buildInputStream($file.f);}
	;
	catch [RecognitionException e] {
		ui.getErrorLogger().logErrorMsg("Error: Invalid script definition.");
		throw new RuntimeException();
	}
	
optAtom
	:	VERBOSE {ui.setVerbose();}
	|	PRINT {ui.setPrint();}
	|	PRINT DELIM file {ui.setPrint($file.f);}
	|	FILTER DELIM script {ui.setCellFilter($script.in);}
	|	SILENT {ui.setSilent();}
	|	TABLE {ui.setTable();}
	;
	catch [RecognitionException e] {
		ui.getErrorLogger().logErrorMsg("Error: Invalid option. Type 'java -jar <jarfile> --help' for usage information.");
		recover(input,e);
	}